package com.yss.sofa.report.engine.test.asserts;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import com.yss.sofa.report.engine.ConnectionFactory;
import com.yss.sofa.report.engine.util.SOFAEnvionmentUtil;
import com.yss.sofa.report.engine.util.ScriptUtil.Db;

public class ConnectionFactorySimulator implements ConnectionFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(Db.class);
    private static Map<String, DataSourceConfig> dataSourceConfigs = new HashMap<String, DataSourceConfig>();
    private static ConnectionFactorySimulator instance = new ConnectionFactorySimulator();
    static {
        initialize();
    }

    public static ConnectionFactory getInstance() {
        return instance;
    }

    @Override
    public Connection getConnection(String code) throws Exception {
        DataSourceConfig config = dataSourceConfigs.get(code);
        if (null == config) {
            throw new RuntimeException("Can not found dataSource : " + code);
        }
        Class.forName(config.driverClassName);
        Connection conn = DriverManager.getConnection(config.url, config.username, config.password);
        return conn;
    }

    @Override
    public int getDbType(String code) throws Exception {
        DataSourceConfig config = dataSourceConfigs.get(code);
        if (null == config) {
            throw new RuntimeException("Can not found dataSource : " + code);
        }
        // if(type.isOracle()){
        // return Const.DB_ORACLE;
        // }
        // if(type.isMYSQL()){
        // return Const.DB_MYSQL;
        // }
        // if(type.isDB2()){
        // return Const.DB_DB2;
        // }
        // if(type.isSQLServer()){
        // return Const.DB_MSSQL;
        // }
        // if(type.isSybase()){
        // return Const.DB_SYBASE;
        // }
        // return Const.DB_OTHER;
        return -1;
    }

    private static void initialize() {
        String path = SOFAEnvionmentUtil.getSOFAHomePath() + "/global/datasources.xml";
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser sp = factory.newSAXParser();
            XMLReader reader = sp.getXMLReader();
            reader.setContentHandler(new DataSourcesXmlHandler());
            reader.parse(new InputSource(new FileInputStream(path)));
        } catch (Exception e) {
            LOGGER.error("load [" + path + "] error", e);
        }
    }

    static class DataSourceConfig {
        private String id;
        private boolean enabled = true;
        private String dbType;
        private Integer connectType;
        private String driverClassName;
        private String url;
        private String username;
        private String password;
        private Integer minPoolSize;
        private Integer maxPoolSize;
        private Integer maxIdleTime;
        private Integer acquisitionTimeout;
        private Boolean shareTransactionConnections;
        private Integer acquireIncrement;
        private Boolean deferConnectionRelease;
        private String testQuery;
    }

    static class DataSourcesXmlHandler extends DefaultHandler {

        private final String PASSWORD_SUFFIX = "__CK_";
        private DataSourceConfig current = null;
        private String currentName = null;

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            if ("datasource".equals(qName)) {
                current = new DataSourceConfig();
                current.id = attributes.getValue("id");
                current.enabled = Boolean.valueOf(attributes.getValue("enabled"));
                current.dbType = attributes.getValue("dbType");
                current.connectType = Integer.parseInt(attributes.getValue("connectType"));
                dataSourceConfigs.put(current.id, current);
            }
            currentName = qName;
        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
            if ("datasource".equals(qName)) {
                current = null;
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            super.characters(ch, start, length);
            if (null == current) {
                return;
            }
            String value = new String(ch, start, length);
            if (StringUtils.isBlank(value)) {
                return;
            }
            if ("driverClassName".equals(currentName)) {
                current.driverClassName = value;
            } else if ("url".equals(currentName)) {
                current.url = value;
            } else if ("username".equals(currentName)) {
                current.username = value;
            } else if ("password".equals(currentName)) {
                current.password = decodePassword(value);
            } else if ("minPoolSize".equals(currentName)) {
                current.minPoolSize = Integer.parseInt(value);
            } else if ("maxPoolSize".equals(currentName)) {
                current.maxPoolSize = Integer.parseInt(value);
            } else if ("maxIdleTime".equals(currentName)) {
                current.maxIdleTime = Integer.parseInt(value);
            } else if ("acquisitionTimeout".equals(currentName)) {
                current.acquisitionTimeout = Integer.parseInt(value);
            } else if ("shareTransactionConnections".equals(currentName)) {
                current.shareTransactionConnections = Boolean.parseBoolean(value);
            } else if ("acquireIncrement".equals(currentName)) {
                current.acquireIncrement = Integer.parseInt(value);
            } else if ("deferConnectionRelease".equals(currentName)) {
                current.deferConnectionRelease = Boolean.parseBoolean(value);
            } else if ("testQuery".equals(currentName)) {
                current.testQuery = value;
            }
        }

        private String decodePassword(String value) {
            if (value.endsWith(PASSWORD_SUFFIX)) {
                value = value.substring(0, value.length() - 5);
                value = new String(java.util.Base64.getDecoder().decode(value.getBytes()));
            }
            return value;
        }

    }

    static enum EDbType {

    }

    public static void main(String[] args) {
        String s = "SOFAREPORT";
        System.out.println(new String(Base64.getEncoder().encode(s.getBytes())));
    }
}
